package com.mes.bac.backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mes.bac.backend.common.exception.BusinessException;
import com.mes.bac.backend.dto.PplanCreateDTO;
import com.mes.bac.backend.dto.PplanItemDTO;
import com.mes.bac.backend.entity.PplanItem;
import com.mes.bac.backend.entity.Piece;
import com.mes.bac.backend.mapper.PplanItemMapper;
import com.mes.bac.backend.mapper.PieceMapper;
import com.mes.bac.backend.service.IPplanService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Slf4j
@Service
public class PplanServiceImpl implements IPplanService {

    @Autowired
    private PplanItemMapper pplanItemMapper;
    @Autowired
    private PieceMapper pieceMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createPplan(PplanCreateDTO pplanCreateDTO) {
        if (pplanCreateDTO == null || CollectionUtils.isEmpty(pplanCreateDTO.getItems())) {
            throw new BusinessException("生产计划或计划条目不能为空");
        }
        QueryWrapper<PplanItem> checkWrapper = new QueryWrapper<>();
        checkWrapper.eq("pplan_sheet", pplanCreateDTO.getPplanSheet()).last("LIMIT 1");
        if (pplanItemMapper.selectCount(checkWrapper) > 0) {
            throw new BusinessException("生产任务单号已存在: " + pplanCreateDTO.getPplanSheet());
        }

        for (PplanItemDTO itemDTO : pplanCreateDTO.getItems()) {
            PplanItem pplanItem = new PplanItem();
            pplanItem.setPplanSheet(pplanCreateDTO.getPplanSheet());
            pplanItem.setPid(itemDTO.getPid());
            pplanItem.setAmount(itemDTO.getAmount());
            pplanItem.setCreateTime(LocalDateTime.now());
            pplanItemMapper.insert(pplanItem);
        }
        log.info("生产计划创建成功, 单号: {}", pplanCreateDTO.getPplanSheet());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generatePiecesFromPlan(String pplanSheetId) {
        QueryWrapper<PplanItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pplan_sheet", pplanSheetId);
        List<PplanItem> items = pplanItemMapper.selectList(queryWrapper);

        if (items.isEmpty()) {
            throw new BusinessException("找不到对应的生产计划: " + pplanSheetId);
        }

        QueryWrapper<Piece> pieceCheckWrapper = new QueryWrapper<>();
        pieceCheckWrapper.in("pplan_item_id", items.stream().map(PplanItem::getId).toList()).last("LIMIT 1");
        if (pieceMapper.selectCount(pieceCheckWrapper) > 0) {
            throw new BusinessException("该计划的工件已生成，请勿重复操作");
        }

        AtomicInteger counter = new AtomicInteger(1);

        for (PplanItem item : items) {
            for (int i = 0; i < item.getAmount(); i++) {
                Piece piece = new Piece();
                String pieceId = String.format("ps%s-%03d", pplanSheetId, counter.getAndIncrement());

                piece.setId(pieceId);
                piece.setPid(item.getPid());
                piece.setPplanItemId(item.getId());
                piece.setCreateTime(LocalDateTime.now());

                pieceMapper.insert(piece);
            }
        }
        log.info("成功为计划 {} 生成了 {} 个工件", pplanSheetId, counter.get() - 1);
    }

    @Override
    public Set<String> getGeneratedPplanSheetIds() {
        List<Piece> pieces = pieceMapper.selectList(new QueryWrapper<Piece>().select("DISTINCT pplan_item_id"));
        if (CollectionUtils.isEmpty(pieces)) {
            return Set.of();
        }
        List<Long> pplanItemIds = pieces.stream().map(Piece::getPplanItemId).toList();

        QueryWrapper<PplanItem> pplanQuery = new QueryWrapper<>();
        pplanQuery.in("id", pplanItemIds).select("DISTINCT pplan_sheet");

        List<PplanItem> pplanItems = pplanItemMapper.selectList(pplanQuery);
        return pplanItems.stream().map(PplanItem::getPplanSheet).collect(Collectors.toSet());
    }
}